package com.tansun.ruledata.data.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.tansun.rule.config.AppConfiguration;
import com.tansun.rule.pojo.EnterPoint;
import com.tansun.rule.utils.MClass;
import com.tansun.rule.utils.MField;
import com.tansun.ruledata.data.dao.RuleDeployDataSetDao;
import com.tansun.ruledata.data.dao.RuleDeployVersionDao;
import com.tansun.ruledata.data.dao.RuleLatestVersionDao;
import com.tansun.ruledata.data.entity.DeployDataparams;
import com.tansun.ruledata.data.entity.DeployDataset;
import com.tansun.ruledata.data.entity.RuleDeployManage;
import com.tansun.ruledata.data.entity.DeployFlowRect;
import com.tansun.ruledata.data.entity.DeployReferenceData;
import com.tansun.ruledata.data.entity.DeployVersionInfo;
import com.tansun.ruledata.data.model.ProjectInfo;
import com.tansun.ruledata.data.service.RuleDeployResourceService;

@Service
public class RuleDeployResourceServiceImpl implements RuleDeployResourceService {
	@Autowired
	private  RuleDeployDataSetDao  ruleDataSetDao;	
	@Autowired
	private  RuleDeployVersionDao  ruleDeployVersionDAO;	
	@Autowired
	private  RuleLatestVersionDao  ruleLatestVersionDao;
	
	@Override
	public   Map<String, MClass>  findMapping(String  projectCode) {
		  Map<String,Object>  paramMap  = new  HashMap<String, Object>();
		  paramMap.put("projectCode", projectCode);
		  List<DeployDataset> list = this.ruleDataSetDao.findRuleDataSet(paramMap);
		  Map<String, MClass> resultMap = new HashMap<String, MClass>();
		  MClass mClass = null;
		
		  for (DeployDataset dataset :list) {
			 mClass = new MClass();
			 mClass.setName(dataset.getName());
			 mClass.setChzn(dataset.getChzn());
			 mClass.setParamType(dataset.getParamType());
			 mClass.setDesc(dataset.getDataDesc());
			 resultMap.put(mClass.getName(), mClass);
			 Map<String,Object> queryMap  = new  HashMap<>();
			 queryMap.put("datasetId", dataset.getId()); 
			 List<DeployDataparams> paramList = this.ruleDataSetDao.findRuleDataParams(queryMap);
			 for (DeployDataparams dataparam : paramList) {
				 MField mField = new MField();
				 BeanUtils.copyProperties(dataparam, mField);
				 mClass.getmFieldNames().add(mField.getName());
				 mClass.getFieldMap().put(mField.getName(), mField);				 
			 }
		  }
		  return  resultMap;
	}

	@Override
	public List<String> findClusterHosts(String type) {
		Map<String,Object>  map  = new  HashMap<>();
		map.put("type", type);
		return  this.ruleDeployVersionDAO.findClusterHosts(map);
	}

	@Override
	public Map<String, EnterPoint> findEnterPoint(String ruleObjectName, String invokePoint) {
		Map<String,Object> paramMap  = new  HashMap<>();
	    paramMap.put("projectCode", ruleObjectName);
	    paramMap.put("invokePoint", invokePoint);
		List<EnterPoint> list =this.ruleDeployVersionDAO.findEnterPoint(paramMap);
	 	 Map<String,EnterPoint>  rMap  = new HashMap<>();
	 	 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	 	 for (EnterPoint enterPoint :list) {
	 		 enterPoint.setUpdateDate(dateFormat.format(new Date()));
	 		rMap.put(enterPoint.getCode(), enterPoint);
	 	 }
		return rMap;
	}
	
	@Override
	public Map<String, List<EnterPoint>> findAllEnterPoint(){
		List<EnterPoint> list = this.ruleDeployVersionDAO.findAllEnterPoint();
	 	 Map<String,List<EnterPoint>>  rMap  = new HashMap<>();
	 	 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	 	 for (EnterPoint enterPoint :list) {
	 		 enterPoint.setUpdateDate(dateFormat.format(new Date()));
	 		if (rMap.get(enterPoint.getProjectCode()) == null) {
	 			rMap.put(enterPoint.getProjectCode(), new ArrayList<>());
	 		}
	 		rMap.get(enterPoint.getProjectCode()).add(enterPoint);
	 	 }
		return rMap;
	}

	@Override
	public List<DeployVersionInfo> findDeployedRuleFlow(String ruleObjectName, String invokePoint) {
		Map<String,Object> paramMap  = new  HashMap<>();
	    paramMap.put("projectCode", ruleObjectName);
	    paramMap.put("enterCode", invokePoint);
		List<RuleDeployManage> list = this.ruleDeployVersionDAO.findDeployManage(paramMap);
		List<DeployVersionInfo> rules = new ArrayList<DeployVersionInfo>();
		for (RuleDeployManage  deployManage: list) {
			Map<String,Object>  queryMap  = new  HashMap<>();
			queryMap.put("id", deployManage.getManageId());
			queryMap.put("projectCode", ruleObjectName);
			queryMap.put("version", deployManage.getManageVersion());
			List<DeployVersionInfo> vlist =this.ruleDeployVersionDAO.findRuleVersionVO(queryMap);
			rules.addAll(vlist);
		}
		return rules;
	}

	@Override
	public Map<String, Collection<DeployVersionInfo>> findLatestRuleVersion(String ruleObjectName, String invokePoint) {
		Map<String,Object> paramMap  = new  HashMap<>();
	    paramMap.put("projectCode", ruleObjectName);
	    paramMap.put("invokePoint", invokePoint);
	    String  refId = null;
		List<EnterPoint> list = this.ruleDeployVersionDAO.findEnterPoint(paramMap);
	  	Map<String,Collection<DeployVersionInfo>>  vmap = new  HashMap<>();
		for (EnterPoint enterPoint :list) {
			 refId  = enterPoint.getRuleflowId();
			 String  code  =null;
			 if (refId != null) {
				String[]  args= StringUtils.split(refId, "_");
				if (args !=null && args.length>0) {
					code  =args[0];
					refId =code;
				}
			 }
			 String  enCode = enterPoint.getCode();
			 
			 Map<String,DeployVersionInfo>  childMap = this.findVersion(ruleObjectName,refId, null, new HashMap<String,DeployVersionInfo>());
			 if (enCode != null){
				 //查找BMPN 文件
				 Map<String,DeployVersionInfo>   bMap  = new  HashMap<>();
				 this.findVersionInfo(ruleObjectName,refId, null, bMap);
				 //this.findFunctionInfo(projectCode, bMap);
				 if (bMap != null && !bMap.isEmpty()){
					 for (String key :bMap.keySet()){
						 childMap.put(key, bMap.get(key));
					 }
					 
				 }    
			 }
			 vmap.put(enCode, new ArrayList<DeployVersionInfo>(childMap.values()));
			
		}
		return vmap;
	}
	
	private  Map<String,DeployVersionInfo>   findVersion(String projectCode,String code ,String version,Map<String,DeployVersionInfo>  vMap){
		ProjectInfo projectInfo = new  ProjectInfo();
		projectInfo.setCode(code);
		projectInfo.setProjectCode(projectCode);
		List<DeployFlowRect> list =this.ruleLatestVersionDao.findRuleFlowRect(projectInfo);
		final Map<String,DeployVersionInfo> conMap = vMap;
		String   rectType = null;
		String   rcode   = null;
		String   rversion = null;
		for (DeployFlowRect  flowRect :list) {
			 rectType =  flowRect.getRectType();
			 rcode  = flowRect.getRectCode();
			 rversion = flowRect.getActiveVersion()  ;
			 if (rcode == null || rcode.startsWith("LS"))//如果是PMML模型，规则流上通过脚本来调用
				 continue;
			   this.findVersionInfo(projectCode,rcode, rversion, conMap);
			   if ("ruleFlow".equals(rectType) || "strategyFlow".equals(rectType)){
					this.findVersion(projectCode,rcode, rversion, conMap);
			   }
			   if ("executionblock".equals(rectType.toLowerCase())){
				   Map<String,Object> paramMap  = new  HashMap<>();
				   paramMap.put("code", rcode);
				   paramMap.put("blockVersion", rversion);
				   paramMap.put("projectCode", projectCode);
				   List<DeployVersionInfo>  bList = this.ruleLatestVersionDao.findRuleExcutionBlock(paramMap);
				   for (DeployVersionInfo bVersion: bList) {
					   this.findVersionInfo(projectCode,bVersion.getModelCode(), bVersion.getVersion(), conMap);
				   }
			   }	 
			
		}
		 return  conMap;
	}
	
    private   void   findVersionInfo(String projectCode,String rcode,String rversion, final Map<String,DeployVersionInfo> conMap) {
		ProjectInfo projectInfo = new  ProjectInfo();
		projectInfo.setCode(rcode);
		projectInfo.setProjectCode(projectCode);
        List<DeployVersionInfo> list =	this.ruleLatestVersionDao.findVersionInfo(projectInfo);
        for (DeployVersionInfo ruleVersion :list) {
        	ruleVersion.setDrlFile(ruleVersion.getModelCode()+"_"+ruleVersion.getVersion());
        	conMap.put(ruleVersion.getManageId()+ruleVersion.getVersion(),ruleVersion); 
        }
    }
    
    @Override
	public     String findEffectiveFunc(String  projectCode){
    	 String  manageId  = "func_"+projectCode;
    	 ProjectInfo  projectInfo  = new  ProjectInfo();
    	 projectInfo.setManageId(manageId);
    	 List<DeployVersionInfo> list = this.ruleDeployVersionDAO.findEffectiveFunc(projectInfo);
         if (list !=null &&  list.size() >0) {
        	 return  list.get(0).getRuleContent();
         }
         return  null;
    }
    
    @Override
    public Map<String,String>  findRuleReleByProjectCode(String  projectCode){
    	 ProjectInfo  projectInfo  = new  ProjectInfo();
    	 projectInfo.setProjectCode(projectCode);
    	 final  Map<String,String>  retMap  = new  HashMap<>();
    	List<DeployVersionInfo> list =this.ruleDeployVersionDAO.findRuleReleByProjectCode(projectInfo);
    	for(DeployVersionInfo  ruleVersion: list) {
    		retMap.put(ruleVersion.getModelCode(), ruleVersion.getRuleContent());
    	}
    	return  retMap;
    	
    }
    
    @Override
    public  Map<String,String>  findPmmlByProjectCode(String projectCode){
    	ProjectInfo projectInfo  =  new  ProjectInfo();
    	projectInfo.setProjectCode(projectCode);
    	List<DeployVersionInfo> list =this.ruleDeployVersionDAO.findPmmlByProjectCode(projectInfo);
    	
    	Map<String,String>  reMap  = new  HashMap<>();
    	for (DeployVersionInfo ruleVersion: list) {
    		reMap.put(ruleVersion.getModelCode(), ruleVersion.getRuleContent());
    	}
    	return  reMap;
    }
    
    @Override
    public Map<String,Map<String, DeployReferenceData>>   findPmmlRefByProjectCode(String  projectCode){
    	Map<String,String> pmmlMap = AppConfiguration.PmmlMap.get(projectCode);
    	Map<String,Map<String, DeployReferenceData>> pmmlRefParamMap = new HashMap<>();
    	if(pmmlMap!=null) {
    		for(Entry<String, String> entry : pmmlMap.entrySet()) {
                ProjectInfo  projectInfo  =  new  ProjectInfo();
                projectInfo.setProjectCode(projectCode);
                projectInfo.setCode(entry.getKey());
                List<DeployReferenceData> list = this.ruleDeployVersionDAO.findPmmlRefByProjectCode(projectInfo);
        		if (list != null){
        			Map<String,DeployReferenceData>  refMap = new HashMap<String, DeployReferenceData>();
        			for (DeployReferenceData ref:list){
        				refMap.put(ref.getRefManageId(), ref);
        			}
        			pmmlRefParamMap.put(entry.getKey(), refMap);
        		}
    		}
    	}
    	return pmmlRefParamMap;
    	
    }

}
